/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

export function getDynamicProperty(obj: any, key: any): any {
  return obj[key];
}

export let value: unknown = 'aaa';

const sym1 = Symbol();

export const symbolToString1 = sym1.toString();

export const symbolValue1 = sym1.valueOf();

export const bol = (symbolValue1 === sym1);

const sym2 = Symbol('description');

export const symbolToString2 = sym2.toString();

export const symbolValue2 = sym2.valueOf();

export const bol1 = (symbolValue2 === sym2);

type IsFunction<T> = T extends Function ? true : false;

export type IsFunctionResult1 = IsFunction<() => void>;

export type IsFunctionResult2 = IsFunction<string>;


export function foo(f: (x: number) => number): number {
  return f(1) + 123;
}

export function foo1(f: (x: number) => number, f1: (x: number) => number): number {
  return f(1) + f(2);
}

export interface Object {
  name: string,
  age?: number,
  readonly isAdmin: boolean,
  greet(): number;
}

export class userObject implements Object {
  name = 'John Doe';
  age? = 30;
  isAdmin = false;
  greet(){
    return 111;
  }
}

export enum HttpStatusCode {
  OK = 200,
  Created = 201,
  CustomError = 'CUSTOM_ERROR'
}

export enum ColorOne {
  Red_1 = 1,
  Green_1,
  Blue_1 = 3,
  Yellow,
  Purple,
  Orange = 'ORANGE',
  CustomColor = 'CUSTOM_COLOR'
}

export enum HttpStatusCode1 {
  OKK = 200,
  NotFound = 404,
  InternalServerError = 500,
  CustomColor = 'CUSTOM_COLOR'
}

export function fooTypeofN(arg: number) {
  return typeof arg;
}

interface User_f {
  id: number;
  name: string;
  age?: number;
  readonly createdAt: Date;
}

export class ClassProperty implements User_f {
  id = 1;
  name = "hello";
  age? = 2;
  readonly createdAt = new Date();
}

export function foo_typeof(arg: ClassProperty) {
  return typeof arg
}

interface User_index {
  name: string;
  age: number;
  isAdmin: boolean;
}

export type NameTypeS = User_index['name']

interface User_1 {
  name: string;
  age: number;
  isAdmin: boolean;
}

const key_s: 'name' | 'age' | 'isAdmin' = 'name';
const key_n: 'name' | 'age' | 'isAdmin' = 'age';
const key_b: 'name' | 'age' | 'isAdmin' = 'isAdmin';

export type DynamicTypeS = User_1[typeof key_s];
export type DynamicTypeN = User_1[typeof key_n];
export type DynamicTypeB = User_1[typeof key_b];

type IsString<T> = T extends string ? true : false;

export type nameTrue = IsString<User_1['name']>;
export type ageFalse = IsString<User_1['age']>;

type TypeA = {
  propA: string;
  commonProp: number;
};

type TypeB = {
  propB: boolean;
  commonProp: string;
};

type UnionType = TypeA | TypeB;

export type CommonPropType = UnionType['commonProp'];

export type IsStringResultS = IsString<string>;
export type IsStringResultN = IsString<number>;

type Flatten<T> = T extends any[] ? T[number] : T;

export type FlattenArrayResultO = Flatten<[string, number, boolean]>;
export type FlattenNonArrayResultS = Flatten<string>;

function toArray<T>(value: T) {
  return [value];
}

export const stringArrayS = toArray('John Doe');
export const numberArrayN = toArray(30);

type ExtractStringOrNumber<T> = T extends string | number ? T : never;

type StringOrNumberResult = ExtractStringOrNumber<string | number | boolean>; // string | number

export const testExtractStringOrNumber = (value: StringOrNumberResult) => {
  if (typeof value === 'string') {
    return "string";
  } else if (typeof value === 'number') {
    return "number";
  }
};

type ReadOnly<T> = {
  readonly [K in keyof T]: T[K];
};

type ReadOnlyUser = ReadOnly<User_1>;

export const readOnlyUser: ReadOnlyUser = {
  name: 'John Doe',
  age: 30,
  isAdmin: false,
};

type Nullable<T> = {
  [K in keyof T]: T[K] | null;
};

type NullableUser = Nullable<User_1>;

export const nullableUser: NullableUser = {
  name: 'John Doe',
  age: 30,
  isAdmin: false,
};

type NonNullable<T> = {
  [K in keyof T]: NonNullable<T[K]>;
};

type NonNullableUser = NonNullable<NullableUser>;

export const nonNullableUser: NonNullableUser = {
  name: 'John Doe',
  age: 30,
  isAdmin: false,
};

type EventConfig<T extends Record<string, any>> = {
  [K in keyof T as `on${Capitalize<string & K>}Event`]: (value: T[K]) => T[K];
};

interface UserConfig {
  name: string;
  age: number;
  isAdmin: boolean;
}

type UserEventConfig = EventConfig<UserConfig>;

export const userEventConfig1: UserEventConfig = {
  onNameEvent(value) {
    return value;
  },
  onAgeEvent(value) {
    return value;
  },
  onIsAdminEvent(value) {
    return value;
  },
};

export type Greeting = `hello ${string}`;

type Role = 'admin' | 'user';
export type UserWithRole = `${string}:${Role}`;

export type IsAdmin<T extends `${string}:${Role}`> = T extends `${string}:admin` ? true : false;

export interface SearchFunc {
  (source: string, subString: string): boolean;
}

export type SearchFunc1 = (source: string, subString: string) => boolean;

export interface SearchFunc2 {
  (source: string, subString: string, caseInsensitive?: boolean): boolean;
}

export interface SumFunc {
  (values: number[]): number;
  (...values: number[]): number;
}

interface ClockConstructor {
  new (hour: number, minute: number): ClockInterface;
  new (settings: { hour: number; minute: number }): ClockInterface;
}

interface ClockInterface {
  tick(): void;
}

export class Clock implements ClockInterface {
  constructor(hour: number, minute: number) {

  }

  tick() {
    return 'Tick!';
  }
}

export class Clock1 implements ClockInterface {
  constructor(hour: number, minute: number) {

  }

  // Multiple constructor implementations are not allowed
  // constructor(settings: { hour: number; minute: number }) {
  //   this.constructor(settings.hour, settings.minute);
  // }

  tick() {
    return 'Tick1!'
  }
}

interface OverloadedFunc {
  (a: number, b: number): number;
  (a: string, b: string): string;
}

export const myOverloadedFunc: OverloadedFunc = function(a: any, b: any): any {
  if (typeof a === 'number' && typeof b === 'number') {
    return a + b;
  } else if (typeof a === 'string' && typeof b === 'string') {
    return a + b;
  } else {
    throw new Error('Invalid arguments');
  }
};

export interface StringIndexedObject {
  [key: string]: string;
}

export interface NumberIndexedObject {
  [key: number]: string;
}

export interface MixedIndexedObject {
  [key: string]: string | number;
  [key: number]: string | number;
}

export interface ReadOnlyStringIndexedObject {
  readonly [key: string]: string;
}

interface Person {
  name: string;
  age: number;
}

interface Developer {
  language: string;
  experience: number;
}

export type PersonAndDeveloper = Person & Developer;

type Predicate = (x: unknown) => boolean;
type NumberPredicate = (x: number) => boolean;

export type PredicateAndNumberPredicate = Predicate & NumberPredicate;

export enum Color {
  Red,
  Green,
  Blue
}

interface Shape {
  color: string | Color;
}

export type ColoredShape = Shape & { color: Color };

interface User {
  name: string;
  age: number;
  isAdmin: boolean;
}

export type UserKeys = keyof User;

export type PartialUser = {
  [K in keyof User]?: User[K];
};

export function fooNum(): number {
  return 1;
}

export let symbolFoo = Symbol("foo");
export let symbolFoo1 = Symbol("foo");


export function dynamicData(param: any):any {
  if (typeof param === 'string') {
    return "string"
  } else if (typeof param === 'number') {
    return 11
  } else if (typeof param === 'boolean') {
    return true
  }
}

export function ClearType(parma: string):string{
  return parma
}

export function foo3(nums: readonly number[]): number {
  // Index signature in type 'readonly number[]' only permits reading.
  //nums[0] = 1;
  return nums.reduce((acc, curr) => acc + curr, 0);
}

export interface UserReadOnly {
  name: string;
  age: number;
}

export function processUser(user: Readonly<UserReadOnly>): string {
  // Cannot assign to 'age' because it is a read-only property
  //user.age = 30;
  return `User: ${user.name}, ${user.age}`;
}